home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Amster - Transfer
- ** by Jacob Laursen <laursen@myself.com>
- */
-
- #include "include/config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/socket.h>
-
- #include <netdb.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <netinet/tcp.h>
- #include <bsdsocket/socketbasetags.h>
- #include <error.h>
- #include <time.h>
-
- #include "include/mui.h"
- #include <MUI/NListview_mcc.h>
- #include "include/download.h"
- #include "include/upload.h"
- #include "include/gui.h"
- #include "include/panel.h"
- #include "include/prefs.h"
- #include "include/transfer.h"
- #include "amster_Cat.h"
- #include "include/protos.h"
-
-
- MUIF translistdisp(REG(a2) char **array, REG(a1) songtrans sd)
- {
- static char bufd2[50], bufd3[50], bufd4[50], bufd5[50];
- static char bufu2[50], bufu3[50], bufu4[50], bufu5[50];
- char *buf2, *buf3, *buf4, *buf5;
-
- static char *states[] = {
- (char *)_MSG_TRANS_STAT_PREPARE,
- (char *)_MSG_TRANS_STAT_QUEUE,
- (char *)_MSG_TRANS_STAT_WAIT,
- (char *)_MSG_TRANS_STAT_CONN,
- (char *)_MSG_TRANS_STAT_REQ,
- (char *)_MSG_TRANS_STAT_INIT,
- (char *)_MSG_TRANS_STAT_DL,
- (char *)_MSG_TRANS_STAT_UL,
- (char *)_MSG_TRANS_STAT_FIN,
- (char *)_MSG_TRANS_STAT_ABORT,
- (char *)_MSG_TRANS_STAT_ERROR,
- NULL
- };
-
- static char *errors[] = {
- (char *)_MSG_TRANS_STAT_ERROR,
- (char *)_MSG_TRANS_ERROR_FILEOPEN,
- (char *)_MSG_TRANS_ERROR_FILEREAD,
- (char *)_MSG_TRANS_ERROR_FILEWRITE,
- (char *)_MSG_TRANS_ERROR_NET_UNKNOWN,
- (char *)_MSG_TRANS_ERROR_LOGGEDOUT,
- (char *)_MSG_TRANS_ERROR_NOTFOUND,
- (char *)_MSG_TRANS_ERROR_INVALIDREQUEST,
- (char *)_MSG_TRANS_ERROR_TEASER,
- (char *)_MSG_TRANS_ERROR_BUSY,
- (char *)_MSG_TRANS_ERROR_NOTREQ,
- (char *)_MSG_TRANS_ERROR_NET_TIMEOUT,
- NULL
- };
-
- static char *NetError[] = {
- (char *)_MSG_TRANS_ERROR_NET_TIMEOUT,
- (char *)_MSG_TRANS_ERROR_NET_REFUSED,
- (char *)_MSG_TRANS_ERROR_NET_RESET,
- (char *)_MSG_TRANS_ERROR_NET_PIPE,
- NULL
- };
-
- if (states[0] == (char *)_MSG_TRANS_STAT_PREPARE)
- localize_array(states);
-
- if (errors[0] == (char *)_MSG_TRANS_STAT_ERROR)
- localize_array(errors);
-
- if (NetError[0] == (char *)_MSG_TRANS_ERROR_NET_TIMEOUT)
- localize_array(NetError);
-
- if (sd) {
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) {
- buf2 = bufd2;
- buf3 = bufd3;
- buf4 = bufd4;
- buf5 = bufd5;
- }
- else {
- buf2 = bufu2;
- buf3 = bufu3;
- buf4 = bufu4;
- buf5 = bufu5;
- }
-
- *array++ = nap_strippath(sd->song->title);
-
- if (sd->state == DLS_WAIT) {
- sprintf(buf5, states[sd->state], sd->ErrorCode);
- *array++ = buf5;
- }
- else if (sd->state != DLS_ERROR)
- *array++ = states[sd->state];
- else {
- switch (sd->error) {
- case ERROR_FILEOPEN:
- case ERROR_FILEREAD:
- case ERROR_FILEWRITE:
- sprintf(buf5, errors[sd->error], sd->ErrorCode);
- *array++ = buf5;
- break;
- case ERROR_NET:
- switch (sd->ErrorCode) {
- case ETIMEDOUT:
- *array++ = NetError[ERROR_NET_TIMEOUT];
- break;
- case ECONNREFUSED:
- *array++ = NetError[ERROR_NET_REFUSED];
- break;
- case ECONNRESET:
- *array++ = NetError[ERROR_NET_RESET];
- break;
- case EPIPE:
- *array++ = NetError[ERROR_NET_PIPE];
- break;
- default:
- sprintf(buf5, errors[sd->error], sd->ErrorCode);
- *array++ = buf5;
- }
- break;
- default:
- *array++ = errors[sd->error];
- }
- }
-
- if (sd->size > 0)
- sprintf(buf2,"\33r%ld / %ld (%d%%)", sd->cur, sd->size, (sd->cur*100+5)/sd->size);
- else sprintf(buf2, "\33r0"); /* Can this happen? */
- *array++ = buf2;
-
- if (sd->cps > 0) {
- if (sd->stalltick < 5 || sd->state >= DLS_FIN) { /* 5 seconds */
- sprintf(buf3, "%d", sd->cps);
- *array++ = buf3;
- }
- else {
- *array++ = (char *)MSG_TRANS_STAT_STALLED;
- }
- sprintf(buf4, "%ld:%02ld / %ld:%02ld", sd->transtime/60, sd->transtime%60, sd->timeleft/60, sd->timeleft%60);
- *array = buf4;
- }
- else {
- *array++ = "-";
- *array = "-";
- }
-
- }
- else {
- *array++ = (char *)MSG_LH_FILE;
- *array++ = (char *)MSG_LH_STATE;
- *array++ = (char *)MSG_LH_SIZE;
- *array++ = (char *)MSG_LH_CPS;
- *array = (char *)MSG_LH_ETIME;
- }
- return 0;
- }
-
-
- MUIF translistdest(REG(a2) APTR pool, REG(a1) songtrans sd)
- {
- nap_songfree(sd->song);
- if (sd->fname) free(sd->fname);
- free(sd);
-
- return 0;
- }
-
-
- ULONG dl_setup(struct IClass *cl, Object *obj, Msg msg)
- {
- struct TransferData *data = INST_DATA(cl, obj);
-
- if (!DoSuperMethodA(cl, obj, msg))
- return(FALSE);
-
- DoMethod(_app(obj), MUIM_Application_AddInputHandler, &data->ihnode);
- /* DoMethod(_app(obj), MUIM_Application_AddInputHandler, &data->watchnode);*/
-
- return(TRUE);
- }
-
-
- ULONG dl_muicleanup(struct IClass *cl, Object *obj, Msg msg)
- {
- struct TransferData *data = INST_DATA(cl,obj);
-
- DoMethod(_app(obj), MUIM_Application_RemInputHandler, &data->ihnode);
- /* DoMethod(_app(obj), MUIM_Application_RemInputHandler, &data->watchnode);*/
-
- return(DoSuperMethodA(cl,obj,msg));
- }
-
-
- void CalculateCps(songtrans sd)
- {
- if (sd->cur != sd->oldsize) {
- sd->stalltick = 0;
- sd->oldsize = sd->cur;
- }
- else sd->stalltick++;
-
- sd->transtime = time(NULL) - sd->starttime;
- if (sd->transtime == 0) sd->transtime = 1;
- sd->cps = (sd->cur - sd->resumestart) / sd->transtime;
- if (sd->cps > 0)
- sd->timeleft = (sd->size - sd->cur) / sd->cps;
- else sd->timeleft = 0;
- }
-
-
- void TransferSetError(struct TransferData *data, char *title, char *user, int error)
- {
- u_long tmp;
- songtrans sd;
- long i;
-
- for (i=0; ; i++) {
- DoMethod(data->list, MUIM_NList_GetEntry, i, &tmp);
- if (!tmp) return;
- sd = (songtrans)tmp;
- if (strcmp(sd->song->title, title) == 0 && stricmp(sd->song->user, user) == 0) break;
- }
-
- if ((sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) && sd->state == DLS_PREP) {
- DoMethod(gui->dwin, DL_COUNTDECREMENT);
- }
-
- sd->state = DLS_ERROR;
- sd->error = error;
-
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) DoMethod(gui->dwin, DL_UPDATE, sd);
- else DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
- }
-
-
- void TransferInfo(struct TransferData *data)
- {
- static char bufd[600], bufu[600];
- char *buf;
- u_long tmp;
- songtrans sd;
-
- GetAttr(MUIA_NList_EntryClick, data->list, &tmp);
- if (tmp == -1 || tmp == -2) return;
- DoMethod(data->list, MUIM_NList_GetEntry, tmp, &sd);
- if (!sd) return;
-
- if (sd->song->ip == 0) return;
-
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) buf = bufd;
- else buf = bufu;
-
- if (sd->host[0] == '\0') {
- sprintf(buf, "%s (%d.%d.%d.%d)", sd->song->user, (sd->song->ip&0xFF000000)>>24, (sd->song->ip&0xFF0000)>>16, (sd->song->ip&0xFF00)>>8, sd->song->ip&0xFF);
- }
- else {
- sprintf(buf, "%s (%s)", sd->song->user, sd->host);
- }
-
- set(data->info, MUIA_Text_Contents, buf);
- }
-
-
- void TransferAbort(struct TransferData *data)
- {
- u_long item;
- songtrans sd;
-
- DoMethod(data->list, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &item);
- if (!item) return;
-
- sd = (songtrans)item;
-
- if (sd->state >= DLS_FIN) {
- return;
- }
-
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) {
- if (sd->state == DLS_WAIT) DoMethod(gui->dwin, DL_REMWAITING, sd);
- if (sd->state == DLS_QUEUE) QueueCount--;
- }
-
- if (sd->t) {
- th_message(sd->t, THC_EXIT, 0);
- Signal(sd->t->task, SIGBREAKF_CTRL_C);
- }
- else {
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) {
- if (sd->state != DLS_QUEUE) {
- DoMethod(gui->dwin, DL_COUNTDECREMENT);
- }
- }
- else DoMethod(gui->uwin, UPLOAD_COUNTDECREMENT);
- }
-
- sd->state = DLS_ABORT;
-
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) DoMethod(gui->dwin, DL_UPDATE, sd);
- else DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
- }
-
-
- void TransferCleanup(struct TransferData *data)
- {
- u_long item;
- int i=0, j;
-
- while (1) {
- DoMethod(data->list, MUIM_NList_GetEntry, i, &item);
- if (!item) break;
- j = ((songtrans)item)->state;
- if (j >= DLS_FIN) DoMethod(data->list, MUIM_NList_Remove, i);
- else i++;
- }
- }
-
-
- void TransferWatcher(struct TransferData *data)
- {
- u_long item;
- long i;
- songtrans sd;
-
- for (i=0; ; i++) {
- DoMethod(data->list, MUIM_NList_GetEntry, i, &item);
- if (!item) break;
- sd = (songtrans)item;
- if (sd->state == DLS_PREP) {
- if (time(NULL)-sd->reqtime > 120) { /* We consider this transfer dead/hanging (never started) */
- sd->state = DLS_ERROR;
- sd->error = ERROR_TIMEOUT;
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) {
- DoMethod(gui->dwin, DL_COUNTDECREMENT);
- DoMethod(gui->dwin, DL_UPDATE, sd);
- }
- else {
- DoMethod(gui->uwin, UPLOAD_COUNTDECREMENT);
- DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
- }
- }
- }
- }
- }
-
-
- void TransferHandleError(songtrans sd)
- {
- char error[128];
-
- if (sd->ErrorCode == EINTR) return; /* Aborted with CTRL-C */
-
- if (sd->error != 0) {
- sd->state = DLS_ERROR;
- if (sd->error >= ERROR_FILEOPEN && sd->error <= ERROR_FILEWRITE) {
- Fault(sd->ErrorCode, "", error, 127);
- gui_debugf((char *)MSG_INFO_IOERROR, sd->fname, error);
- }
- else if (sd->error >= ERROR_OUTOFBOUND) sd->error = ERROR_UNKNOWN;
- prf_event(PRFE_DLERROR);
- }
- else if (sd->state == DLS_FIN) {
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) prf_event(PRFE_DLFINISH);
- else prf_event(PRFE_ULFINISH);
- }
-
- if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) DoMethod(gui->dwin, DL_UPDATE, sd);
- else DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
- }
-
-
- /* Thread stuff */
-
- BOOL InitTransferThread(thread t, songtrans sd)
- {
- struct Library *DosBase;
- struct Library *SocketBase;
- char *buffer;
- long s;
- long tmp;
- struct hostent *he;
-
- sd->state = DLS_PREP;
-
- sd->nsig = AllocSignal(-1);
- if (sd->nsig == -1) {
- ExitTransferThread(sd, 49);
- return FALSE;
- }
- sd->nsigm = (1L << (sd->nsig));
- sd->msigm = (1L << (t->port->mp_SigBit));
-
- DosBase = OpenLibrary("dos.library", 0);
- if (!DosBase) {
- ExitTransferThread(sd, 50);
- return FALSE;
- }
- sd->DosBase = DosBase;
-
- SocketBase = OpenLibrary("bsdsocket.library", 0);
- if (!SocketBase) {
- ExitTransferThread(sd, 51);
- return FALSE;
- }
- sd->SocketBase = SocketBase;
-
- SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK), (char *)sd->nsigm, TAG_DONE);
-
- buffer = malloc(8192);
- if (!buffer) {
- ExitTransferThread(sd, 52);
- return FALSE;
- }
- sd->buffer = buffer;
-
- /* Perform DNS-lookup */
- he = gethostbyname(Inet_NtoA(sd->song->ip));
- he = gethostbyaddr(he->h_addr_list[0], he->h_length, AF_INET);
- if (he != 0) strcpy(sd->host, he->h_name);
- else strcpy(sd->host, Inet_NtoA(sd->song->ip));
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0) {
- ExitTransferThread(sd, 53);
- return FALSE;
- }
- sd->s = s;
-
- sd->sin.sin_addr.s_addr = sd->ip;
- sd->sin.sin_port = htons(sd->port);
- sd->sin.sin_family = AF_INET;
- sd->sin.sin_len = sizeof(sd->sin);
-
- tmp = 1;
- IoctlSocket(s, FIOASYNC, (char *)&tmp);
- IoctlSocket(s, FIONBIO, (char *)&tmp);
- /* Asynchronous and non-blocking I/O to the socket */
-
- tmp = connect(s, (struct sockaddr *)&sd->sin, sizeof(sd->sin));
- if (tmp == -1 && Errno() != EINPROGRESS) {
- sd->ErrorCode = Errno();
- ExitTransferThread(sd, ERROR_NET);
- return FALSE;
- }
-
- thr_message(t, DLC_STATE, (APTR)DLS_CON);
-
- return TRUE;
- }
-
-
- void ExitTransferThread(songtrans sd, int ret)
- {
- struct Library *DosBase=sd->DosBase;
- struct Library *SocketBase=sd->SocketBase;
-
- if (sd->nsig != -1) FreeSignal(sd->nsig);
- sd->nsig = -1;
-
- if (sd->f) Close(sd->f);
- sd->f = 0;
-
- if (sd->s != -1) CloseSocket(sd->s);
- sd->s = -1;
-
- if (sd->buffer) free(sd->buffer);
- sd->buffer = NULL;
-
- if (SocketBase) CloseLibrary(SocketBase);
- sd->SocketBase = NULL;
-
- if (DosBase) CloseLibrary(DosBase);
- sd->DosBase = NULL;
-
- thr_exit(sd->t, ret);
- }
-